home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 8
/
QRZ Ham Radio Callsign Database - Volume 8.iso
/
pc
/
files
/
dsp
/
56200tar.z
/
56200tar
/
56200
/
p3
< prev
next >
Wrap
Text File
|
1992-04-28
|
26KB
|
519 lines
/***********************************************\
|** **|
|** DSP56200 CHIP DRIVER -ADAPTIVE FILTER **|
|** -INTERRUPT DRIVEN **|
|** **|
\***********************************************/
/************************************************************************\
* *
* This is an example of a program located in a host processor, used *
* to setup and service the DSP56200 as a real-time adaptive filter. *
* In this example, the host processor is interrupted at the beginning *
* of every new sample period, signified by the reception of a rising *
* edge on the DSP56200's START pin. The host processor's interrupt *
* pin is tied to the START pin of the DSP56200 through an inverter. *
* *
* This program, written in the language "C", is provided only as an *
* example, and will be much faster if translated by the user into the *
* assembly language of the host processor. *
* *
* *
* The example system is configured as shown below: *
* *
* *
* ------------ *
* | DSP56200 | *
* ------------ *
* ^ *
* | *
* v *
* ------- ------------------ *
* d(t) -->| A/D |--->| Host Processor | *
* ------- | | ------- *
* | (contains code |--->| D/A |--> out(t) *
* ------- | found in this | ------- *
* x1(t) -->| A/D |--->| file) | *
* ------- ------------------ *
* *
* *
* Figure 1. Adaptive Filtering System *
* *
* *
* *
* There is only one DSP56200 in this example (i.e., not multiple *
* DSP56200s in cascade), and it is configured as an adaptive filter *
* (see Figure 2) by writing the DSP56200's Configuration register. *
* Since only 16 bits of the result are sent to the D/A Converter, *
* the output is rounded to a 16 bit result by the DSP56200. *
* *
* *
* *
* *
* d(n) ------------------------------- *
* - | *
* v *
* -------------- + --- *
* x1(n) ----->| FIR |------->| + |-----> out(n) *
* | Structure | --- = -1 * error *
* -------------- | *
* ^ | *
* | | *
* ------------------- *
* *
* *
* Figure 2. DSP56200 Configuration *
* *
* *
* *
* ************************************************************ *
* * * *
* * This program originally available on the Motorola DSP * *
* * bulletin board. It is provided under a DISCLAMER OF * *
* * WARRANTY available from Motorola DSP Operation, * *
* * 6501 Wm. Cannon Drive W., Austin, Tx., 78735. * *
* * * *
* ************************************************************ *
* *
* *
* *
* ************************************************************ *
* * Note on the Representation of Hex Numbers: * *
* * * *
* * In the programming language "C", hex numbers are * *
* * represented by preceding the number with "0x". For * *
* * example, e4 (hex) is represented in "C" as 0xe4. * *
* * * *
* ************************************************************ *
* *
\************************************************************************/
/*** CONSTANTS ***/
#define PASS_CONFIG 3 /* Pass for Configuring the DSP56200 */
#define PASS_RAMINIT 2 /* Pass for Initializing the RAMs */
#define PASS_ENABLE 1 /* Pass for Enabling Coeff Updates */
#define PASS_REALTIM 0 /* Pass for Realtime Filtering */
#define X1_HI 0x0 /* Addresses (hex) of DSP56200 regs, bank 0 */
#define X1_LO 0x1
#define D_HI 0x2
#define D_LO 0x3
#define K_HI 0x4
#define K_LO 0x5
#define X2_HI 0x6 /* unused -Dual FIR mode only */
#define X2_LO 0x7 /* unused -Dual FIR mode only */
#define DATA_HI 0x8 /* unused */
#define DATA_LO 0x9 /* unused */
#define COEFF_HI 0xa
#define COEFF_MD 0xb
#define COEFF_LO 0xc
#define RAM_ADR 0xd
#define CONFIG 0xf
#define OUTPUT3 0x0 /* Most significant byte of result */
#define OUTPUT2 0x1
#define OUTPUT1 0x2 /* Two least significant bytes are */
#define OUTPUT0 0x3 /* unused since rounded to 16 bits */
#define LTAP1_HI 0x4 /* unused */
#define LTAP1_LO 0x5 /* unused */
#define LTAP2_HI 0x6 /* unused */
#define LTAP2_LO 0x7 /* unused */
#define LEAKAGE 0x0 /* Addresses (hex) of DSP56200 regs, bank 1 */
#define FTL 0x1
#define LKG_VAL 0x00 /* Values (hex) written to the DSP56200 regs */
#define FTL_VAL 0xff /* 256 taps */
#define DCONFIG_0 0x98 /* Updates disabled, Selects bank 0 */
#define DCONFIG_1 0x99 /* Updates disabled, Selects bank 1 */
#define ECONFIG_0 0x90 /* Updates enabled, Selects bank 0 */
#define KVAL_HI 0x04
#define KVAL_LO 0x00 /* It may be desirable to make the K
register a variable so it can be
updated every sample period. */
/*** GLOBAL VARS ***/
int tap; /* filter tap number */
int passnum; /* Determines action taken by the
interrupt service routine when
a START interrupt is received. */
/*** MAIN PROGRAM ***/
main() {
/********************************************************************\
* *
* This program is an example of the software used by a host *
* processor to service a DSP56200 configured as an adaptive *
* filter. Three functions are performed: *
* *
* 1. Initialize User's System and Configure the DSP56200. *
* 2. Zero the Coeff and Data RAMs of the DSP56200. *
* 3. Run the Adaptive Filter in a real-time environment. *
* *
* Things to watch for when setting up an adaptive filter system: *
* *
* - There must be NO GLITCHES on the DSP56200's START pin. *
* - The SEI pin must be directly wired to the SSO pin. *
* - The value of the K register must not be too large. *
* - If codecs are used for the A/D or D/A conversion, see *
* comments in the routines "send_da()"and "get_ad()". *
* - If offset binary A/Ds or D/As are used, see comments *
* in the subroutines "send_da()" and "get_ad()". *
* *
* Note: The program assumes that the variable type "int" is at *
* least 16 bits wide. *
* *
\********************************************************************/
/* Program Setup */
/* The host must disable the START Interrupt */
/* Then, global vars are set up for the routine "irealtime()" */
passnum = PASS_CONFIG;
tap = 0;
/* Initialize System */
/* Here the user first initializes any other components of the */
/* adaptive filtering system which require initialization. The */
/* DSP56200 is then initialized using the program code below. */
/* The host must now enable the START Interrupt */
/* Run the Adaptive Filter in Real-time */
/* At this point the program can either start executing some */
/* other task or it can idle. Upon reception of a START signal */
/* (i.e. when interrupted), the host calls the interrupt service */
/* routine "irealtime()". Upon completion of "irealtime()", */
/* the host either continues its other processing or idles. */
}
/*** SUBROUTINES ***/
/* IREALTIME */
irealtime()
{
/****************************************************************\
* *
* This interrupt service routine will perform one of the *
* following four tasks when executed: *
* *
* Task 1. Configure the DSP56200. *
* *
* Task 2. Clear one location in the Data RAM and *
* one location in the Coefficient RAM. *
* *
* Task 3. Enable Updates of the Coefficients. *
* *
* Task 4. Send two new data samples to the DSP56200 *
* and read out one error term from the chip. *
* *
* When the user's system comes out of reset, the DSP56200 is *
* first configured (Task 1). Then, the host processor will *
* execute Task 2 when interrupted so that the DSP56200 RAMs *
* get initialized. Upon receiving each new interrupt, Task 2 *
* is executed until the RAM initialization is completed. The *
* host processor then uses one sample period (i.e. the next *
* interrupt) to enable updates of the coefficients. From this *
* time on, the host executes Task 4 with each new interrupt it *
* receives. If the user wants to update the value of the K *
* (loop gain) register, it could also be done within Task 4. *
* *
* This routine is used only in interrupt driven systems. *
* Since this is an interrupt service routine, it may be *
* necessary to save the status of the host processor upon *
* entering this routine, and to restore the processor's *
* status upon exiting this routine. It may also be important *
* to disable any interrupts of lower priority when entering *
* this routine, and to reenable these interrupts upon exiting. *
* *
* Note: The routine assumes that the variable type "int" is *
* at least 16 bits wide. *
* *
* Also: The DSP56200 outputs "-1 * error". If the correct *
* sign for the error term is required, then the host *
* processor must perform a 2's complement operation *
* on the 16 bit value read from the DSP56200's OUTPUT *
* register (bytes 3 and 2). *
* *
* Also: It is important that execution of this routine *
* completes before the next START interrupt arrives, *
* i.e., it must complete in one sample period. If *
* Task 1 will not complete in one sample period, it *
* can be broken into two shorter tasks, requiring *
* two sample periods. *
* *
\****************************************************************/
/* Subroutine Declarations */
int x1, d, out; /* see Figure 2 */
/* Select Correct Task to Execute */
/* TASK 1 */
if (passnum == PASS_CONFIG) {
/* Reset and Configure the DSP56200 */
wrbyte(DCONFIG_1, CONFIG); /* Configuration: */
/* - Single Adaptive Filter */
/* - Not Cascaded */
/* - 16 Bit Rounding */
/* - Coeff Update Disabled */
/* - DC Tap Disabled */
/* - Leakage Disabled */
/* - Register Bank 1 Selected */
wrbyte(FTL_VAL, FTL); /* Writing this reg also resets */
/* the chip at the beginning */
/* of the next sample period, */
/* which destroys any previous */
/* contents of the Data RAM. */
wrbyte(LKG_VAL, LEAKAGE);
wrbyte(DCONFIG_0, CONFIG); /* Switch to register bank 0 */
wrbyte(KVAL_HI, K_HI);
wrbyte(KVAL_LO, K_LO);
/* Setup the DSP56200 registers for RAM initialization */
wrbyte(0, X1_HI); /* clears Data RAM when loading coeffs */
wrbyte(0, X1_LO);
wrbyte(0, D_HI);
wrbyte(0, D_LO);
wrbyte(0, COEFF_HI); /* Coeff_RAM[0] = 0 */
wrbyte(0, COEFF_MD);
wrbyte(0, COEFF_LO);
wrbyte(0, RAM_ADR); /* autoincrements w/ each START */
passnum = passnum-1; /* Goes to PASS_RAMINIT on */
/* next START interrupt */
/* Exit Routine */
return;
}
/* TASK 2 */
if (passnum == PASS_RAMINIT) {
/* Clear 1 Location in the DSP56200's Coefficient and Data RAMS */
tap = tap + 1;
wrbyte(0, COEFF_HI); /* Coeff_RAM[tap] = 0 */
wrbyte(0, COEFF_MD);
wrbyte(0, COEFF_LO);
/* Note that the Data RAM is also */
/* cleared since the DSP56200's X1 */
/* reg is set to "0", resulting in */
/* "0"s being "shifted" into the */
/* filter's Data RAM (delay line) */
/* every sample period. */
if (tap == FTL_VAL)
passnum = passnum-1; /* Goes to PASS_ENABLE on
next START interrupt */
/* Exit Routine */
return;
}
/* TASK 3 */
if (passnum == PASS_ENABLE) {
wrbyte(ECONFIG_0, CONFIG); /* Enables coeff updates by
toggling bit 3 to "0" */
passnum = passnum-1; /* Goes to PASS_REALTIM on
next START interrupt */
return; /* Exit Routine */
}
/* TASK 4 */
if (passnum == PASS_REALTIM) {
/* Read the New Samples from the A/Ds and Write to the DSP56200 */
x1 = get_ad(1);
d = get_ad(2);
wrbyte((x1>>8) & 0x0ff, X1_HI); /* writes upper byte */
wrbyte( x1 & 0x0ff, X1_LO); /* writes lower byte */
wrbyte((d>>8) & 0x0ff, D_HI); /* writes upper byte */
wrbyte( d & 0x0ff, D_LO); /* writes lower byte */
/* Read Error Term from the 56200 and Write to the D/A */
out = rdbyte(OUTPUT3);
out = out << 8; /* move to upper byte */
out = out + (0x0ff & rdbyte(OUTPUT2));
send_da(out);
/* Exit Routine */
return;
}
}
/* WRBYTE */
wrbyte(val,adr)
int val, adr;
{
/**************************************************************\
* *
* This subroutine writes one byte to the DSP56200 register *
* specified by "adr". *
* Note that the correct register bank has already been *
* selected (defined by the LSB of the Configuration reg). *
* *
* This subroutine could be defined as a macro for faster *
* execution. *
* *
* Inputs: *
* val = bytewide value to be written to the DSP56200 *
* adr = address of the DSP56200 register to be written *
* *
\**************************************************************/
/* Actual program code depends on the user's system. */
}
/* RDBYTE */
rdbyte(adr)
int adr;
{
/**************************************************************\
* *
* This subroutine reads one byte from the DSP56200 register *
* specified by "adr". *
* Note that the correct register bank has already been *
* selected (defined by the LSB of the Configuration reg). *
* *
* This subroutine could be defined as a macro for faster *
* execution. *
* *
* Inputs: *
* adr = address of the DSP56200 register to be read *
* *
* Outputs: *
* The routine returns the byte read from the DSP56200 *
* *
\**************************************************************/
int valread;
/* Actual program code depends on the user's system. */
return(valread);
}
/* GET_AD */
get_ad(devnum)
int devnum;
{
/******************************************************************\
* *
* This subroutine returns a 16 bit value read from one of the *
* two A/D converters in the filtering system. *
* *
* Inputs: *
* devnum = A/D Converter number: 1 = x1 input, 2 = d input. *
* *
* Outputs: *
* The routine returns the value read from the selected A/D. *
* *
\******************************************************************/
int ad_val;
/* Actual program code depends on the user's system. */
/* If a codec is used for A/D conversion, the 8 bit companded */
/* sample must be converted into a 12 bit linear quantity and */
/* then sign extended to 16 bits. */
/* If the converter uses an offset binary format, it may be */
/* necessary to invert the sign bit (and any sign extension */
/* bits) to obtain a 2's complement number. */
return(ad_val);
}
/* SEND_DA */
send_da(val)
int val;
{
/**************************************************************\
* *
* This subroutine sends a value to a D/A converter where it *
* gets converted to an analog signal. *
* *
* Inputs: *
* val = value to be sent to the D/A converter *
* *
\**************************************************************/
/* Actual program code depends on the user's system. */
/* If a codec is used for D/A conversion, the 16 bit linear */
/* sample must be converted into a 8 bit companded quantity. */
/* If the converter uses an offset binary format, it may be */
/* necessary to invert the sign bit (and any sign extension */
/* bits) to obtain a number in offset binary format. */
}